// VideoWidget.cpp
#include "Work.h"
#include "VideoWidget.h"

using namespace std;
VideoWidget::VideoWidget(QWidget* parent)
    : QWidget(parent)
    , graphicsView(nullptr)
    , scene(nullptr)
    , timer(nullptr)
    , frameCounter(0)
    , workerThread(nullptr)
    , worker(nullptr)
    , openPoseLoaded(false)
    , audioInput(nullptr)
    , audioOutput(nullptr)
    , audioBuffer(nullptr)
    , microphoneOpened(false)
    , telephoneReceiverOpened(false)
{
    // 创建 UI
    QVBoxLayout* mainLayout = new QVBoxLayout(this);

    // 创建视频显示区域
    scene = new QGraphicsScene(this);
    graphicsView = new CustomGraphicsView(this);
    graphicsView->setScene(scene);
    graphicsView->viewport()->installEventFilter(this);

    // 设置图形视图属性
    graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
    graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    graphicsView->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
    graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    // 创建音频控制按钮
    QHBoxLayout* audioLayout = new QHBoxLayout();
    btnOpenMicrophone = new QPushButton("开启麦克风");
    btnOpenTelephoneReceiver = new QPushButton("开启听筒");
    btnCloseMicrophone = new QPushButton("关闭麦克风");
    btnCloseTelephoneReceiver = new QPushButton("关闭听筒");

    btnCloseMicrophone->setEnabled(false);
    btnCloseTelephoneReceiver->setEnabled(false);

    audioLayout->addWidget(btnOpenMicrophone);
    audioLayout->addWidget(btnCloseMicrophone);
    audioLayout->addWidget(btnOpenTelephoneReceiver);
    audioLayout->addWidget(btnCloseTelephoneReceiver);
    audioLayout->addStretch();

    // 添加到主布局
    mainLayout->addWidget(graphicsView);
    mainLayout->addLayout(audioLayout);

    // 初始化多线程处理
    workerThread = new QThread(this);
    worker = new Worker();
    worker->moveToThread(workerThread);

    // 连接信号槽
    connect(this, &VideoWidget::frameToProcess, worker, &Worker::processFrame);
    connect(worker, &Worker::frameProcessed, this, &VideoWidget::updateDisplay);
    connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);

    // 连接音频按钮信号
    connect(btnOpenMicrophone, &QPushButton::clicked, this, &VideoWidget::onOpenMicrophone);
    connect(btnOpenTelephoneReceiver, &QPushButton::clicked, this, &VideoWidget::onOpenTelephoneReceiverLocation);
    connect(btnCloseMicrophone, &QPushButton::clicked, this, &VideoWidget::onCloseMicrophone);
    connect(btnCloseTelephoneReceiver, &QPushButton::clicked, this, &VideoWidget::onCloseTelephoneReceiver);
   
    // 监听播放状态
    connect(audioOutputLocation, &QAudioSink::stateChanged, [this](QAudio::State state) {
        qDebug() << "音频输出状态改变:" << state;
        if (state == QAudio::IdleState) {
            // 播放完成
            qDebug() << "音频播放完成";
            // 可以在这里添加播放完成后的处理
        }
        });

    // 初始化组件
    initializeOpenPose();
    initializeCamera();
    initializeAudio();

    // 启动工作线程
    workerThread->start();

    // 启动定时器捕获视频帧
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &VideoWidget::captureFrame);
    timer->start(33); // 约30fps
}

VideoWidget::~VideoWidget()
{
    // 停止定时器
    if (timer && timer->isActive()) {
        timer->stop();
    }

    // 停止工作线程
    if (workerThread && workerThread->isRunning()) {
        workerThread->quit();
        workerThread->wait(1000);
    }

    // 释放摄像头
    if (capture.isOpened()) {
        capture.release();
    }

    // 释放音频资源
    if (audioInput) {
        audioInput->destroyed();
        delete audioInput;
    }
    if (audioOutput) {
        audioOutput->destroyed();
        delete audioOutput;
    }
    if (audioBuffer) {
        delete audioBuffer;
    }
}

void VideoWidget::initializeCamera()
{
    // 检查摄像头可用性
    cv::VideoCapture testCap;
    bool cameraAvailable = testCap.open(0);
    testCap.release();

    if (!cameraAvailable) {
        QMessageBox::warning(this, "警告", "未检测到可用的摄像头设备");
       // return;
    }

    // 打开摄像头
    capture = cv::VideoCapture(0);
    if (!capture.isOpened()) {
        QMessageBox::warning(this, "警告", "摄像头打开失败");
       // return;
    }
}

void VideoWidget::initializeOpenPose()
{
    try {
        string protoFile = "C:/Users/xiejun/source/repos/qnode/qGameVideo/model/openpose_pose_coco.prototxt";
        string weightsFile = "C:/Users/xiejun/source/repos/qnode/qGameVideo/model/pose_iter_440000.caffemodel";

        openPoseNet = cv::dnn::readNetFromCaffe(protoFile, weightsFile);

        // 设置后端（简化版本，移除复杂的异常处理）
        openPoseNet.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
        openPoseNet.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

        openPoseLoaded = true;
        qDebug() << "OpenPose 模型加载成功";

        // 将网络传递给Worker
        if (worker) {
           // worker->setOpenPoseNet(&openPoseNet);
        }
    }
    catch (const std::exception& e) {
        qDebug() << "OpenPose 模型加载失败:" << e.what();
        openPoseLoaded = false;
    }
}

void VideoWidget::initializeAudio()
{
    // 初始化音频缓冲区
    audioBuffer = new QBuffer(this);
    audioBuffer->open(QIODevice::ReadWrite);

    qDebug() << "音频系统初始化完成";
}

void VideoWidget::captureFrame()
{
    if (!capture.isOpened()) {
        return;
    }

    cv::Mat frame;
    capture >> frame;
    if (frame.empty()) {
        return;
    }

    frameCounter++;

    // 降低处理频率
    bool processThisFrame = (frameCounter % 5 == 0); // 每5帧处理一次

    // 降低分辨率处理
    cv::Mat smallFrame;
    cv::resize(frame, smallFrame, cv::Size(320, 240));

    // 发送到工作线程处理
    emit frameToProcess(smallFrame.clone(), openPoseLoaded && processThisFrame);
}

void VideoWidget::updateDisplay(const QImage& image)
{
    if (!graphicsView || !graphicsView->scene()) {
        return;
    }

    // 限制UI更新频率
    static QTime lastUpdate = QTime::currentTime();
    if (lastUpdate.msecsTo(QTime::currentTime()) < 33) {
        return;
    }
    lastUpdate = QTime::currentTime();

    QGraphicsScene* currentScene = graphicsView->scene();
    currentScene->clear();

    QGraphicsPixmapItem* pixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(image));
    currentScene->addItem(pixmapItem);

    // 首次显示时适应窗口大小
    static bool firstDisplay = true;
    if (firstDisplay && currentScene->itemsBoundingRect().isValid()) {
        graphicsView->fitInView(currentScene->itemsBoundingRect(), Qt::KeepAspectRatio);
        firstDisplay = false;
    }
}

void VideoWidget::onOpenTelephoneReceiver(QString soundFile)
{
    if (telephoneReceiverOpened) {
        QMessageBox::information(this, "提示", "听筒已经开启");
        return;
    }

    // 检查声音文件是否存在
    //QString soundFile = "C:\\Users\\xiejun\\Documents\\录音\\录音.m4a";
    if (!QFile::exists(soundFile)) {
        QMessageBox::warning(this, "错误", "声音文件不存在");
        return;
    }

    // 清理之前的媒体播放器（如果有）
    if (mediaPlayer) {
        mediaPlayer->stop();
        delete mediaPlayer;
        mediaPlayer = nullptr;
    }
    if (audioOutput) {
        delete audioOutput;
        audioOutput = nullptr;
    }

    try {
        mediaPlayer = new QMediaPlayer(this);
        audioOutput = new QAudioOutput(this);

        mediaPlayer->setAudioOutput(audioOutput);
        audioOutput->setVolume(0.8f);

        mediaPlayer->setSource(QUrl::fromLocalFile(soundFile));
        connect(mediaPlayer, &QMediaPlayer::playbackStateChanged, this, [this](QMediaPlayer::PlaybackState state) {
            if (state == QMediaPlayer::StoppedState) {
                qDebug() << "声音播放完成";
            }
            });

        connect(mediaPlayer, &QMediaPlayer::errorOccurred, this, [this](QMediaPlayer::Error error, const QString& errorString) {
            QMessageBox::warning(this, "播放错误", QString("播放声音文件失败: %1").arg(errorString));
            qDebug() << "媒体播放错误:" << errorString;
            // 播放出错时，清理资源
            telephoneReceiverOpened = false;
            btnOpenTelephoneReceiver->setEnabled(true);
            btnCloseTelephoneReceiver->setEnabled(false);
            });

        mediaPlayer->play();

        telephoneReceiverOpened = true;
        btnOpenTelephoneReceiver->setEnabled(false);
        btnCloseTelephoneReceiver->setEnabled(true);

        qDebug() << "听筒开启成功并开始播放声音";
        QMessageBox::information(this, "成功", "听筒已开启并开始播放声音");

    }
    catch (const std::exception& e) {
        QMessageBox::warning(this, "错误", QString("听筒开启失败: %1").arg(e.what()));
        // 发生异常时，清理资源
        if (mediaPlayer) {
            delete mediaPlayer;
            mediaPlayer = nullptr;
        }
        if (audioOutput) {
            delete audioOutput;
            audioOutput = nullptr;
        }
    }
}

void VideoWidget::onOpenTelephoneReceiverLocation()
{
    if (telephoneReceiverOpened) {
        QMessageBox::information(this, "提示", "听筒已经开启");
        return;
    }

    // 检查是否有音频数据可供播放
    if (!audioBuffer || audioBuffer->buffer().isEmpty()) {
        QMessageBox::warning(this, "错误", "没有可播放的音频数据");
        return;
    }

    // 清理之前的媒体播放器（如果有）
    if (mediaPlayer) {
        mediaPlayer->stop();
        delete mediaPlayer;
        mediaPlayer = nullptr;
    }
    if (audioOutput) {
        delete audioOutput;
        audioOutput = nullptr;
    }

    try {
        // 重置缓冲区位置以便从头播放
        audioBuffer->seek(0);

        // 创建音频输出设备
        QAudioDevice outputDevice = QMediaDevices::defaultAudioOutput();
        if (outputDevice.isNull()) {
            QMessageBox::warning(this, "错误", "未找到可用的音频输出设备");
            return;
        }

        // 设置音频格式 - 需要与录制时的格式匹配
        QAudioFormat format;
        format.setSampleRate(8000);
        format.setChannelCount(1);
        format.setSampleFormat(QAudioFormat::Int16);

        // 创建音频输出
        audioOutputLocation = new QAudioSink(outputDevice, format, this);

        // 设置音量
        audioOutputLocation->setVolume(0.8f);

        // 开始播放音频缓冲区
        audioOutputLocation->start(audioBuffer);

        telephoneReceiverOpened = true;
        btnOpenTelephoneReceiver->setEnabled(false);
        btnCloseTelephoneReceiver->setEnabled(true);

        qDebug() << "听筒开启成功，开始播放音频缓冲区";
        QMessageBox::information(this, "成功", "听筒已开启并开始播放音频数据");



    }
    catch (const std::exception& e) {
        QMessageBox::warning(this, "错误", QString("听筒开启失败: %1").arg(e.what()));
        // 发生异常时，清理资源
        if (audioOutput) {
            delete audioOutput;
            audioOutput = nullptr;
        }
        telephoneReceiverOpened = false;
        btnOpenTelephoneReceiver->setEnabled(true);
        btnCloseTelephoneReceiver->setEnabled(false);
    }
}


void VideoWidget::onCloseTelephoneReceiver()
{
    if (!telephoneReceiverOpened) {
        return;
    }

    if (mediaPlayer) {
        mediaPlayer->stop();
        delete mediaPlayer;
        mediaPlayer = nullptr;
    }

    if (audioOutput) {
        delete audioOutput;
        audioOutput = nullptr;
    }

    telephoneReceiverOpened = false;
    btnOpenTelephoneReceiver->setEnabled(true);
    btnCloseTelephoneReceiver->setEnabled(false);

    qDebug() << "听筒已关闭";
}

void VideoWidget::onCloseMicrophone()
{
    if (!microphoneOpened || !audioSource) {
        return;
    }

    audioSource->stop();
    delete audioSource;
    audioSource = nullptr;

    microphoneOpened = false;
    btnOpenMicrophone->setEnabled(true);
    btnCloseMicrophone->setEnabled(false);

    qDebug() << "麦克风已关闭";
    QMessageBox::information(this, "提示", "麦克风已关闭");
}

void VideoWidget::onOpenMicrophone()
{
    if (microphoneOpened) {
        QMessageBox::information(this, "提示", "麦克风已经开启");
        return;
    }

    try {
        // 获取音频输入设备 - Qt6方式
        QAudioDevice inputDevice = QMediaDevices::defaultAudioInput();
        if (inputDevice.isNull()) {
            QMessageBox::warning(this, "错误", "未找到可用的麦克风设备");
            return;
        }

        // 设置音频格式 - Qt6方式
        QAudioFormat format;
        format.setSampleRate(8000);
        format.setChannelCount(1);
        format.setSampleFormat(QAudioFormat::Int16);

        // 检查格式是否支持
        if (!inputDevice.isFormatSupported(format)) {
            qDebug() << "请求的音频格式不支持，尝试使用支持的格式";

            // 获取设备支持的格式并选择一个合适的
            QList<QAudioFormat> supportedFormats;

            // 尝试找到最接近的格式
            for (int sampleRate : {8000, 16000, 44100, 48000}) {
                for (int channels : {1, 2}) {
                    for (auto sampleFormat : { QAudioFormat::Int16, QAudioFormat::UInt8, QAudioFormat::Float }) {
                        QAudioFormat testFormat;
                        testFormat.setSampleRate(sampleRate);
                        testFormat.setChannelCount(channels);
                        testFormat.setSampleFormat(sampleFormat);

                        if (inputDevice.isFormatSupported(testFormat)) {
                            supportedFormats.append(testFormat);
                            qDebug() << "支持的格式: 采样率" << sampleRate
                                << "通道" << channels
                                << "格式" << sampleFormat;
                        }
                    }
                }
            }

            if (!supportedFormats.isEmpty()) {
                // 选择第一个支持的格式，或者可以根据需要选择最合适的
                format = supportedFormats.first();
                qDebug() << "使用替代格式: 采样率" << format.sampleRate()
                    << "通道" << format.channelCount()
                    << "格式" << format.sampleFormat();
            }
            else {
                QMessageBox::warning(this, "错误", "没有找到支持的音频格式");
                return;
            }
        }

        // 创建音频输入 - Qt6方式
        audioSource = new QAudioSource(inputDevice, format, this);

        // 创建缓冲区
        if (!audioBuffer) {
            audioBuffer = new QBuffer(this);
            audioBuffer->open(QIODevice::ReadWrite);
        }
        else {
            audioBuffer->buffer().clear();
            audioBuffer->seek(0);
        }

        // 开始录制
        audioSource->start(audioBuffer);

   
        microphoneOpened = true;
        btnOpenMicrophone->setEnabled(false);
        btnCloseMicrophone->setEnabled(true);

        qDebug() << "麦克风开启成功 - 设备:" << inputDevice.description()
            << "格式: 采样率" << format.sampleRate()
            << "通道" << format.channelCount()
            << "格式类型" << format.sampleFormat();
        QMessageBox::information(this, "成功", "麦克风已开启");

    }
    catch (const std::exception& e) {
        QMessageBox::warning(this, "错误", QString("麦克风开启失败: %1").arg(e.what()));
        qDebug() << "麦克风开启异常:" << e.what();
    }
}


bool VideoWidget::eventFilter(QObject* obj, QEvent* event)
{
    if (obj == graphicsView->viewport() && event->type() == QEvent::Wheel) {
        QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);

        if (wheelEvent->angleDelta().y() > 0) {
            graphicsView->scale(1.2, 1.2);
        }
        else {
            graphicsView->scale(0.8, 0.8);
        }
        return true;
    }
    return QWidget::eventFilter(obj, event);
}